using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using UnityEngine;
using Voodoo.Sauce.CrashReport;
using Voodoo.Sauce.Internal;
using Voodoo.Sauce.Internal.IntegrationCheck;

namespace Voodoo.Sauce.Core
{
	internal static class VoodooSauceCore
	{
		private const string TAG = "VoodooSauceCore";

		private static readonly IAPCore _iap;

		private static readonly CrashReportCore _crashReport;

		private static readonly List<IModule> _moduleList;

		private static VoodooSauceBehaviour _voodooSauceBehaviour;

		private static TModule InstantiateModule<TModule>() where TModule : class, IModule, new()
		{
			return InstantiateChildClass<TModule>() ?? ((TModule)Activator.CreateInstance(typeof(TModule)));
		}

		private static TModule GetModuleInstance<TModule>(TModule moduleInstance, bool logWarning) where TModule : class, IModule, new()
		{
			if (logWarning)
			{
				Type type = moduleInstance.GetType();
				if (type.BaseType == null || type.BaseType == typeof(object))
				{
					VoodooLog.LogWarning(Voodoo.Sauce.Internal.Module.COMMON, "VoodooSauceCore", type.Name + " module is not available/implemented.");
				}
			}
			return moduleInstance;
		}

		[CanBeNull]
		private static TParentClass InstantiateChildClass<TParentClass>() where TParentClass : class
		{
			Type typeFromHandle = typeof(TParentClass);
			TParentClass val = null;
			foreach (Type item in AppDomain.CurrentDomain.GetAssemblies().SelectMany((Assembly assembly) => assembly.GetTypes()))
			{
				if (!(typeFromHandle == item) && typeFromHandle.IsAssignableFrom(item) && !item.IsInterface && !item.IsAbstract)
				{
					if (val != null)
					{
						VoodooLog.LogError(Voodoo.Sauce.Internal.Module.COMMON, "VoodooSauceCore", "More than one child class has been found for " + typeFromHandle.Name);
						break;
					}
					val = (TParentClass)Activator.CreateInstance(item);
				}
			}
			return val;
		}

		static VoodooSauceCore()
		{
			_moduleList = new List<IModule>();
			_crashReport = InstantiateModule<CrashReportCore>();
			_iap = InstantiateModule<IAPCore>();
		}

		public static void Initialize(VoodooSauceBehaviour voodooSauceBehaviour)
		{
			_voodooSauceBehaviour = voodooSauceBehaviour;
		}

		public static List<IntegrationCheckMessage> IntegrationCheck(VoodooSettings settings)
		{
			return _iap.IntegrationCheck(settings);
		}

		internal static IAPCore GetInAppPurchase(bool logWarning = false)
		{
			return GetModuleInstance(_iap, logWarning);
		}

		public static Coroutine StartCoroutine(IEnumerator routine)
		{
			return _voodooSauceBehaviour.StartCoroutine(routine);
		}

		public static void StopCoroutine(IEnumerator routine)
		{
			_voodooSauceBehaviour.StopCoroutine(routine);
		}

		public static void StopCoroutine(Coroutine coroutine)
		{
			_voodooSauceBehaviour.StopCoroutine(coroutine);
		}

		internal static CrashReportCore GetCrashReport(bool logWarning = false)
		{
			return GetModuleInstance(_crashReport, logWarning);
		}
	}
}
